﻿#include "PlayerBehaviorRecorderModule.h"

fast_io::dir_file PlayerBehavior_Dir{};

std::shared_mutex player_recorder_mutex{};
std::map<uint64_t, player_recorder_struct> player_recorder{};

void onDisable_PlayerBehaviorRecorderModule() {
	[[maybe_unused]] const auto lock{std::shared_lock{player_recorder_mutex}};
	player_recorder.clear();
};

void onTick_PlayerBehaviorRecorderModule(C_GameMode* gm) {
	C_LocalPlayer* localPlayer{GameData::getLocalPlayer()};

	const auto pos{*localPlayer->getPos()};

	if (localPlayer == nullptr) 
		return;

	const uint32_t tickCountNow{*(uint32_t*)((uintptr_t)localPlayer->getlevel() + 0x690)};

	GameData::forEachEntity([localPlayer, pos, tickCountNow](C_Entity* ent) {
		if (ent->isPlayer()) {
			const auto playername{ent->getNameTag()->getString()};
			if (playername.empty()) [[unlikely]]
				return;

			[[maybe_unused]] const auto lock{std::shared_lock{player_recorder_mutex}};

			const auto uniqueid{ent->getUniqueId()};

			fast_io::u8obuf_file_mutex* file{};

			if (auto i{player_recorder.find(uniqueid)}; i != player_recorder.end()) {
				if (i->second.tick != tickCountNow - 1) {
					println(i->second.file,
							tickCountNow,
							u8", Players REJOIN: ",
							playername,
							u8", UniqueID: ",
							uniqueid);
				}
				i->second.tick = tickCountNow;
				file = &i->second.file;
			} else {
				auto& player_recorder_d = player_recorder[uniqueid];
				player_recorder_d.tick = tickCountNow;
				player_recorder_d.file.reopen(at(PlayerBehavior_Dir), fast_io::u8concat(playername, u8".txt"), fast_io::open_mode::text | fast_io::open_mode::app);
				println(player_recorder_d.file,
						u8"Tick: ",
						tickCountNow,
						u8", Player: ",
						playername,
						u8", UniqueID: ",
						uniqueid);
				file = &player_recorder_d.file;
			}

			const auto entpos{*ent->getPos()};
			const auto entoldpos{*ent->getPosOld()};

			Attribute healthAttribute{Attribute_type::HealthAttribute};

			print(*file,
				  u8"Tick: ",
				  tickCountNow,
				  u8", Player: ",
				  playername,
				  u8", UniqueID: ",
				  uniqueid,
				  u8". YawSpeed = ",
				  ent->getYawSpeedInDegreesPerSecond() / *GameData::getClientInstance()->minecraft->timer,
				  u8", dist = ",
				  dist(pos, *ent->getPos()),
				  u8", Motion (X = ",
				  ent->velocity.x,
				  u8", Y = ",
				  ent->velocity.y,
				  u8", Z = ",
				  ent->velocity.z,
				  u8") Yaw = ",
				  ent->yaw,
				  u8", Pitch = ",
				  ent->pitch,
				  u8", BodyYaw = ",
				  ent->bodyYaw,
				  u8", OldBodyYaw = ",
				  ent->oldBodyYaw,
				  u8", Position (X = ",
				  entpos.x,
				  u8", Y = ",
				  entpos.y,
				  u8", Z = ",
				  entpos.z,
				  u8", Old Position (X = ",
				  entoldpos.x,
				  u8", Y = ",
				  entoldpos.y,
				  u8", Z = ",
				  entoldpos.z,
				  u8") BPT = ",
				  dist(entpos, entoldpos),
				  u8" ,Health = ",
				  ent->getAttribute(&healthAttribute)->currentValue,
				  u8" .");

			//...
			if (ent->canSee(localPlayer))
				print(*file, u8"canSee localPlayer, ");

			if (ent->isJumping())
				print(*file, u8"isJumping, ");
			if (ent->isFlying)
				print(*file, u8"isFlying, ");
			if (ent->isSneaking())
				print(*file, u8"isSneaking, ");
			if (ent->isBlocking())
				print(*file, u8"isBlocking, ");
			if (ent->isCreative())
				print(*file, u8"isCreative, ");
			if (ent->isOnFire())
				print(*file, u8"isOnFire, ");
			if (ent->isOnHotBlock())
				print(*file, u8"isOnHotBlock, ");
			if (ent->isFireImmune())
				print(*file, u8"isFireImmune, ");
			if (ent->isImmobile())
				print(*file, u8"isImmobile, ");
			if (ent->isInLava())
				print(*file, u8"isInLava, ");
			if (ent->isInWall())
				print(*file, u8"isInWall, ");
			if (ent->isInWater())
				print(*file, u8"isInWater, ");
			if (ent->isOverWater())
				print(*file, u8"isOverWater, ");
			if (ent->isSleeping())
				print(*file, u8"isSleeping, ");
			if (ent->isInvertedHealAndHarm())
				print(*file, u8"isInvertedHealAndHarm, ");
			if (ent->isInvisible())
				print(*file, u8"isInvisible, ");
			if (ent->isInvisible())
				print(*file, u8"isInvisible, ");
			if (ent->isLookingAtAnEntity())
				print(*file, u8"isLookingAtAnEntity, ");
			if (ent->isAlive())
				print(*file, u8"isAlive, ");
			if (ent->isCreativeModeAllowed())
				print(*file, u8"isCreativeModeAllowed, ");
			if (ent->isAffectedByWaterBottle())
				print(*file, u8"isAffectedByWaterBottle, ");
			if (ent->isAdventure())
				print(*file, u8"isAdventure, ");
			print(*file, fast_io::mnp::chvw(u8'\n'));

		}
	});
}

IModule PlayerBehaviorRecorderModule{
	Category::CUSTOM,
	{u8"PlayerRec", u8"玩家行为记录器", u8"玩家行為記錄器", u8"プレイヤー行動レコーダー"},
	{u8"Player Behavior Recorder", u8"玩家行为记录器", u8"玩家行為記錄器", u8"プレイヤー行動レコーダー"},
	0,  // keybind
	fast_io::vector<SettingEntry>{},
	nullptr,
	nullptr,
	nullptr,
	nullptr,
	&onTick_PlayerBehaviorRecorderModule};